using Tycho.Parser.Peg;

namespace Tycho.Grammar {
    class TermGrammarBuilder : IGrammarBuilder {
        public IProduction Production {
            get {
                var everything = new ChoiceProduction ();
                everything.Productions = new[] {
                                                   BuildCompositeTermProduction (everything),
                                                   BuildListTermProduction (everything),
                                                   BuildExpressionProduction (),
                                                   IdentifierProduction.CreateTerminal (),
                                                   IntegerProduction.CreateTerminal (),
                                                   StringProduction.CreateTerminal (),
                                               };

                return everything;
            }
        }

        private static IProduction BuildCompositeTermProduction (IProduction everything) {
            var openParen = new KeywordRule ("{");
            var closeParen = new KeywordRule ("}");
            var termName = new NamedRule ("name", IdentifierProduction.CreateTerminal ());
            var delimiter = new ChoiceRule(new KeywordRule (","), new KeywordRule (";"));
            var subTerms = new DelimitedRule (new NamedRule("sub-terms", CreateSubTermProduction (everything)), delimiter);
            return new NonTerminal ("composite-term", new SequenceRule (termName, openParen, subTerms, closeParen), new [] {"sub-terms"});
        }

        private static IProduction CreateSubTermProduction (IProduction everything) {
            var colon = new KeywordRule (":");
            var name = new NamedRule ("name", IdentifierProduction.CreateTerminal ());
            var value = new NamedRule ("term", everything);
            return new NonTerminal("sub-term", new SequenceRule (name, colon, value));
        }

        private static IProduction BuildListTermProduction (IProduction everything) {
            var openBracket = new KeywordRule ("[");
            var closeBracket = new KeywordRule ("]");
            var delimiter = new ChoiceRule (new KeywordRule (","), new KeywordRule (";"));
            var terms = new DelimitedRule (new NamedRule ("terms", everything), delimiter);

            var rule = new SequenceRule (openBracket,
                                         terms,
                                         closeBracket);

            return new NonTerminal ("list-term", rule, new[] {"terms"});
        }

        private static IProduction BuildExpressionProduction () {
            var unquote = new KeywordRule ("#");
            var name = new NamedRule ("name", IdentifierProduction.CreateTerminal ());
            var rules = new SequenceRule (unquote, name);
            return new NonTerminal ("expression", rules);
        }
    }
}